package controllers

import (
	"encoding/json"
	"fmt"
	"strconv"
	"time"

	"boomlive.com/boomlive-common/constants"
	"boomlive.com/boomlive-common/utils"
	"boomlive.com/boomlive-openapi-game/dtos"
	"boomlive.com/boomlive-openapi-game/services"
	"github.com/beego/beego/v2/core/logs"
)

type JoyplayController struct {
	BaseController
}

var Redisserver *utils.RedisService

func init() {
	Redisserver = new(utils.RedisService)
}

// @router /joyplay/game/getUserInfo [get]
func (c *JoyplayController) UserInfo() {
	// 处理 Authorization
	authorization := c.Ctx.Input.Header("Authorization")
	token, code := services.HandleJoyplayAuthorization(authorization)
	if code != constants.SUCCESS {
		c.Error("services.HandleJoyplayAuthorization error,token=%s,code=%d", token, code) // 保持原有日志
		c.CodeResult(code, nil)
		return
	}
	logs.Info("token=%s", token)

	encodedExt := c.Ctx.Input.Header("ext")
	logs.Info("encodedExt=%s", encodedExt)

	extParams, err := services.ParseExtParam(encodedExt)
	if err != nil {
		c.Error("services.HandleJoyplayExtParams(encodedExt: %s) error: %v", encodedExt, err)
		c.CodeResult(constants.ERR_JOYPLAY_EXT_PARAM_DECODING_FAILED, nil)
		return
	}
	logs.Info("extParams=%+v", extParams)

	useridx, err := strconv.ParseInt(extParams.UserID, 10, 64)
	if err != nil {
		// 处理转换错误
		c.Error("strconv.ParseInt(extParams.UserID: %s) error: %v", extParams.UserID, err)
		c.CodeResult(constants.ERR_JOYPLAY_DECODE_USER_FAILED, nil)
	}
	logs.Info("useridx=%d", useridx)

	// 验证token
	checked := services.CheckToken(useridx, token)
	if !checked {
		logs.Error("error: Invalid token,CheckToken(%d, %s)", useridx, token)
		c.CodeResult(constants.ERR_JOYPLAY_INVALID_TOKEN, nil)
		return
	}
	logs.Info("CheckToken : checked=%v", checked)

	var joyPlayUser services.JoyPlayUserInfo

	// 查询用户基本信息
	userBaseInfo, err := services.GetUserInfo(useridx)
	if err != nil {
		logs.Error("services.GetUserInfo(%d) error: %v", useridx, err)
		c.CodeResult(constants.ERR_JOYPLAY_USER_NOT_EXIST, nil)
	}
	logs.Info("userBaseInfo=%+v", userBaseInfo)

	// 查询用户余额
	userBalance, err := services.GetUserBalance(useridx)
	if err != nil {
		logs.Error("services.GetUserBalance(%d) error: %v", useridx, err)
		c.CodeResult(constants.ERR_JOYPLAY_COINS_NOT_EXIST, nil)
	}
	logs.Info("useridx=%d, userBalance=%d", useridx, userBalance)

	// 组装用户信息
	avatarUrl := services.GetUFullImgSrc(useridx, userBaseInfo.PhotoNum)
	joyPlayUser = services.JoyPlayUserInfo{
		UserId:         fmt.Sprintf("%d", useridx),
		AvailableCoins: userBalance,
		AvatarUrl:      avatarUrl,
		Nickname:       userBaseInfo.NickNm,
		PkgName:        extParams.PkgName,
		//Level:    userinfo.Level,
	}

	c.CodeResult(constants.SUCCESS, joyPlayUser)
	return
}

// @router /joyplay/game/submitFlow [post]
func (c *JoyplayController) SubmitFlow() {
	// 处理 Authorization
	authorization := c.Ctx.Input.Header("Authorization")
	token, code := services.HandleJoyplayAuthorization(authorization)
	if code != constants.SUCCESS {
		c.Error("services.HandleJoyplayAuthorization error,token=%s,code=%d", token, code) // 保持原有日志
		c.CodeResult(code, nil)
		return
	}
	logs.Info("token=%s", token)

	req := dtos.SubmitFlowParams{}
	body := c.Ctx.Input.RequestBody
	if len(body) == 0 {
		c.Error("请求体为空")
		c.CodeResult(constants.ERR_PARAM, nil)
		return
	}
	logs.Info("raw request body: %s\n", string(c.Ctx.Input.RequestBody))

	if err := json.Unmarshal(body, &req); err != nil {
		c.Error("JSON解析失败: %v", err)
		c.CodeResult(constants.ERR_PARAM, nil)
		return
	}

	// 获取加密的 HEX 数据
	requestData := req.Data

	// 解密流程
	decryptedBytes, err := services.DecryptData(requestData)
	if err != nil {
		c.Error("error: services.DecryptData(requestData: %s) err: %v", requestData, err)
		c.CodeResult(constants.ERR_JOYPLAY_REQUEST_DATA_DECRYPT_FAILED, nil)
		return
	}
	logs.Info("decryptedBytes=%s", string(decryptedBytes))

	// 3. 处理业务逻辑（如解析 JSON）
	var joyPlayFlowParam dtos.JoyPlayFlowParam
	if err = json.Unmarshal(decryptedBytes, &joyPlayFlowParam); err != nil {
		c.Error("json.Unmarshal(%s, &joyPlayFlowParam)error: json.Unmarshal error=%v", decryptedBytes, err)
		c.CodeResult(constants.ERR_JOYPLAY_JSON_UNMARSHAL_FAILED, nil)
		return
	}
	logs.Info("提交流水提交记录 ：joyPlayFlowParam=%+v", joyPlayFlowParam)

	encodedExt := joyPlayFlowParam.Ext

	extParams, err := services.ParseExtParam(encodedExt)
	if err != nil {
		c.Error("services.HandleJoyplayExtParams(encodedExt: %s) error: %v", encodedExt, err)
		c.CodeResult(constants.ERR_JOYPLAY_EXT_PARAM_DECODING_FAILED, nil)
		return
	}
	logs.Info("extParams=%+v", extParams)

	useridx, err := strconv.ParseInt(extParams.UserID, 10, 64)
	if err != nil {
		// 处理转换错误
		c.Error("strconv.ParseInt(extParams.UserID: %s) error: %v", extParams.UserID, err)
		c.CodeResult(constants.ERR_JOYPLAY_DECODE_USER_FAILED, nil)
	}
	logs.Info("useridx=%d", useridx)

	// 验证token
	checked := services.CheckToken(useridx, token)
	if !checked {
		logs.Error("error: Invalid token,CheckToken(%d, %s)", useridx, token)
		c.CodeResult(constants.ERR_JOYPLAY_INVALID_TOKEN, nil)
		return
	}
	logs.Info("CheckToken : checked=%v", checked)

	// ... 处理流水逻辑
	playFlowType := joyPlayFlowParam.Type
	coins := joyPlayFlowParam.Coins

	if playFlowType == 1 {
		// 1：减金币 2：加金币
		coins = -coins
	}

	joyPlayTradeInfo := &services.KiwiSubmitFlowRequest{
		Gameid:   extParams.GameId,
		Coin:     coins,
		Token:    token,
		AnchorID: extParams.AnchorID,
		UserID:   extParams.UserID,
		Ext:      encodedExt,
	}
	logs.Info("joyPlayTradeInfo=%+v", joyPlayTradeInfo)

	// 只有加金币或 coins > 0 时才需要获取 linkid
	if playFlowType == 2 || coins > 0 {
		linkid, err := getLinkIDWithRetry(joyPlayFlowParam.RoundId, 5)
		if err != nil {
			logs.Error("Failed to get linkid for RoundId=%d: %v", joyPlayFlowParam.RoundId, err)
			c.CodeResult(constants.ERR_JOYPLAY_GET_LINKID_FAILED, nil)
			return
		}
		joyPlayTradeInfo.Linkid = linkid
	}
	resp, err := services.KiwiSubmitFlow(joyPlayTradeInfo)
	logs.Info("services.KiwiSubmitFlow(%+v) return resp=%v, err=%v", joyPlayTradeInfo, resp, err)
	if err != nil {
		logs.Error("services.KiwiSubmitFlow(%+v) error: %v", joyPlayTradeInfo, err)
		c.CodeResult(constants.ERR_JOYPLAY_KIWI_SUBMIT_FLOW_FAILED, nil)
	}
	logs.Info("services.KiwiSubmitFlow(%+v) return resp=%+v", joyPlayTradeInfo, resp)

	if resp.Code != "E_OK" {
		logs.Error("services.KiwiSubmitFlow(%+v) return resp.Code != E_OK, resp: %+v", joyPlayTradeInfo, resp)
		c.CodeResult(constants.ERR_JOYPLAY_KIWI_SUBMIT_FLOW_FAILED, nil)
	}

	// 如果是减金币，缓存流水订单id
	if playFlowType == 1 {
		// 缓存流水订单id
		Redisserver.Set(fmt.Sprintf("KIWI::JOYPLAY::SUBMITFLOW::LINKID::%s", joyPlayFlowParam.RoundId), resp.Linkid, 10*time.Minute)
	}

	data := map[string]interface{}{
		"availableCoin": resp.RestMoney,
	}

	c.CodeResult(constants.SUCCESS, data)
	return
}

// Redis 获取 linkid，重试最多 n 次，每次间隔 1 秒
func getLinkIDWithRetry(roundID string, n int) (string, error) {
	var linkid string
	var err error

	if n <= 0 {
		n = 3
	}
	for i := 0; i < n; i++ {
		linkid, err = Redisserver.Get(fmt.Sprintf("KIWI::JOYPLAY::SUBMITFLOW::LINKID::%s", roundID))
		if err != nil {
			logs.Error("Redisserver.Get error: %v (retry %d)", err, i+1)
		}

		if linkid != "" {
			return linkid, nil
		}

		if i < 2 { // 最后一次不用 sleep
			time.Sleep(1 * time.Second)
		}
	}
	return "", fmt.Errorf("Failed to get linkid for RoundId=%s after %d retries", roundID, n)
}
